#include "runcommand.h"
#include <Poco/StringTokenizer.h>
#include <Poco/Process.h>
using Poco::StringTokenizer;
using Poco::Process;
using Poco::ProcessHandle;

#include <sstream>
using std::ostringstream;

#include <iostream>
using std::cout;
using std::endl;

#include <Poco/DOM/DOMParser.h>
using Poco::XML::DOMParser;

#include <Poco/DOM/DOMWriter.h>
using Poco::XML::DOMWriter;

#include <Poco/DOM/Element.h>
using Poco::XML::Element;

#include <Poco/DOM/Text.h>
using Poco::XML::Text;

#include <Poco/DOM/NodeList.h>
using Poco::XML::NodeList;

namespace Commands {

	const string RunCommand::NAME = "Run";

	RunCommand::RunCommand(string const& cmdline) :
		fCmd(),
		fArgs()
	{
		StringTokenizer ss(cmdline," ");
		fCmd = ss[0];
		for (size_t i = 1; i < ss.count(); ++i)
		{
			fArgs.append(ss[i]);
			if(i < ss.count()-1)
				fArgs.append(" ");
		}
	}
	
	RunCommand::~RunCommand()
	{}
	
	void RunCommand::execute()
	{
		Process::Args args;
		StringTokenizer ss(fArgs, " ");
		for (StringTokenizer::Iterator s = ss.begin(); s != ss.end(); ++s)
			args.push_back(*s);

		ProcessHandle cmd = Process::launch(fCmd,args);
	}
	
	string RunCommand::name()
	{
		return string(RunCommand::NAME);
	}
				
	void RunCommand::undo()
	{
		throw NotImplemented();
	}
			
	string RunCommand::repr(){
		ostringstream out;
		DOMWriter w;
		w.writeNode(out, toXML());
		return out.str();

	}
			
	CommandCreator RunCommand::creator(){
		return &RunCommand::makeCommand;
	}

	Document* RunCommand::toXML(Document* )
	{
		Document* doc = new Document();
		
		//What do we want to run
		string comm = fCmd; comm.append(" "); comm.append(fArgs);
		Text* cli = doc->createTextNode(comm);
		Element* cliE = doc->createElement("commandline");
		cliE->appendChild(cli);
		doc->appendChild(cliE);

		return Command::toXML(doc);
	}
	
	Command* RunCommand::makeCommand(string r, void* )
	{
		DOMParser parser;
		Document* doc = parser.parseString(r);

		//Get the commandline
		string comm = ((Element*)(doc->getElementsByTagName("commandline")->item(0)))->innerText();
		cout << "RunCommand :: Creating Command :: " << comm << endl;

		return new RunCommand(comm);
	}
}

